/*
 * All of the documentation and software included in the
 * Alchemy Software is copyrighted by Stanley Kok, Parag
 * Singla, Matthew Richardson, Pedro Domingos, Marc
 * Sumner, Hoifung Poon, and Daniel Lowd.
 * 
 * Copyright [2004-08] Stanley Kok, Parag Singla, Matthew
 * Richardson, Pedro Domingos, Marc Sumner, Hoifung
 * Poon, and Daniel Lowd. All rights reserved.
 * 
 * Contact: Pedro Domingos, University of Washington
 * (pedrod@cs.washington.edu).
 * 
 * Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that
 * the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above
 * copyright notice, this list of conditions and the
 * following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the
 * above copyright notice, this list of conditions and the
 * following disclaimer in the documentation and/or other
 * materials provided with the distribution.
 * 
 * 3. All advertising materials mentioning features or use
 * of this software must display the following
 * acknowledgment: "This product includes software
 * developed by Stanley Kok, Parag Singla, Matthew
 * Richardson, Pedro Domingos, Marc Sumner, Hoifung
 * Poon, and Daniel Lowd in the Department of Computer Science and
 * Engineering at the University of Washington".
 * 
 * 4. Your publications acknowledge the use or
 * contribution made by the Software to your research
 * using the following citation(s): 
 * Stanley Kok, Parag Singla, Matthew Richardson and
 * Pedro Domingos (2005). "The Alchemy System for
 * Statistical Relational AI", Technical Report,
 * Department of Computer Science and Engineering,
 * University of Washington, Seattle, WA.
 * http://www.cs.washington.edu/ai/alchemy.
 * 
 * 5. Neither the name of the University of Washington nor
 * the names of its contributors may be used to endorse or
 * promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
 * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
 * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */
#ifndef TWOWAYMESSAGE_H_
#define TWOWAYMESSAGE_H_


/******************************************************************************/
// for storing the messages
/******************************************************************************/
class TwoWayMessage
{
 public:
  TwoWayMessage(double nodeToFactorMsgs[], double factorToNodeMsgs[])
  {
    for(int i = 0; i < 2; i++)
    {
      nodeToFactorMsgs_[i] = nodeToFactorMsgs[i];
      factorToNodeMsgs_[i] = factorToNodeMsgs[i];
    }
  }

  ~TwoWayMessage() {}

  double * getNodeToFactorMessage() { return nodeToFactorMsgs_;}
  double * getFactorToNodeMessage() { return factorToNodeMsgs_;}

 private:
  double nodeToFactorMsgs_[2];
  double factorToNodeMsgs_[2];
};

class LinkId
{
 public:
  LinkId(int predId, int superPredId, int superClauseId, int predIndex)
  {
    predId_ = predId;
    superPredId_ = superPredId;
    superClauseId_ = superClauseId;
    predIndex_ = predIndex;
    dirty_ = true;
  }
          
  ~LinkId(){}

  int getPredId() { return predId_;}
  int getSuperPredId() { return superPredId_; }
  int getSuperClauseId() { return superClauseId_; }
  int getPredIndex() { return predIndex_; }
     
  size_t getHashCode()
  {
    if (!dirty_) return hashCode_;
    hashCode_ = predId_;
    hashCode_ = hashCode_*31 + superPredId_;
    hashCode_ = hashCode_*31 + superClauseId_;
    hashCode_ = hashCode_*31 + predIndex_;
    dirty_ = false;
    return hashCode_;
  }

 private:
  int predId_;
  int superPredId_;
  int superClauseId_;
  int predIndex_;
      
  size_t hashCode_;
  bool dirty_;
};


class HashLinkId
{
 public:
  size_t operator()(LinkId * const & lid) const
  {
    return lid->getHashCode();
  }
};


class EqualLinkId
{
 public:
  bool operator()(LinkId * const & lid1, LinkId * const & lid2)
  { 
    return (lid1->getPredId() == lid2->getPredId() &&
            lid1->getSuperPredId() == lid2->getSuperPredId() &&
            lid1->getSuperClauseId() == lid2->getSuperClauseId() &&
            lid1->getPredIndex() == lid2->getPredIndex());
  }
};

typedef hash_map<LinkId*, TwoWayMessage*, HashLinkId, EqualLinkId>
  LinkIdToTwoWayMessageMap;

#endif /*TWOWAYMESSAGE_H_*/

